package Controllers;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;

import Boundry.EvaluationPanel;
import Boundry.EvaluationReportPanel;
import Boundry.ReevaluationPanel;
import Boundry.SetTimeForEvaluationPanel;
import Boundry.SuspendRequestPanel;
import Boundry.GenericTools.GenericTabel;
import Boundry.GenericTools.RequestTableListPanel;
import Controllers.GenericToolsForController.BaseClass;
import Controllers.GenericToolsForController.PDFfile;
import Controllers.GenericToolsForController.RequestMainStatusEnum;
import Controllers.GenericToolsForController.RequestStepStatusEnum;
import Entity.EvaluationReport;
import Entity.InfoSystem;
import Entity.Report;
import Entity.ReportType;
import Entity.Request;
import Entity.RequestArray;
import Entity.RequestStatusHistory;
import Entity.Status;
import Entity.Worker;
import Exception.ICMException;
/**
 * 
 * @author G16
 *
 */
public class EvaluatorController extends BaseClass 
{
	/*
	 * Singleton 
	 */
	private static  EvaluatorController Instance = null;

	private RequestArray requestsToEvaluate;
	private RequestArray requestsToReEvaluate;
	private RequestArray requestsToSetTime;
	private RequestArray requestsWithTimePending;
	
	private EvaluationPanel evaluationPanel;
	private EvaluationReportPanel evaluationReportPanel;

	private String[] fieldsInTable;
	private String[][] strMtrxAllOpenRequests;
	private String[][] strMtrxRequestsToEvaluate;
	private String[][] strMtrxRequestsToReEvaluate;
	private String[][] strMtrxRequestsToSetTime;
	private String[][] strMtrxRequestsWithTimePending;
	
	private ArrayList <JComponent> jcompListToBlink;
	private int startingIndex ;
	private int[] numberOfTupples;
	private static final int NUMOFTABS = 4;
	
	private Request currentRequest;
	public Worker evaluator;
	protected int dataEnteredCounter;

	private SetTimeForEvaluationPanel setTimeForEvaluation;

	private boolean sendMailOn = true;

	private ReevaluationPanel myReevaluationPanel;
	
	
	private EvaluatorController(){	}
	/**
	 *  getInstance for singleton proposes
	 * @return instance
	 */
	public static EvaluatorController getInstance()
	{
		if(Instance == null)
		{
			Instance = new EvaluatorController();
		}
		return Instance;
	}
	/**
	 * This void method define and initialize all parameters.
	 */
	private void init() 
	{
		fieldsInTable = RequestArray.getEvaluationCommonFields();
		numberOfTupples = new int[NUMOFTABS];
		this.requestsToEvaluate = new RequestArray();
		this.requestsToReEvaluate = new RequestArray();
		this.requestsToSetTime = new RequestArray();
		this.requestsWithTimePending = new RequestArray();
		strMtrxAllOpenRequests =  null;
		strMtrxRequestsToEvaluate =  null;
		strMtrxRequestsToReEvaluate=  null;
		strMtrxRequestsToSetTime=  null;
		strMtrxRequestsWithTimePending=  null;
		System.out.println("finished init");
	}
	/**
	 * evlautaion  - This is the main flow of the evaluation proccess. It set up the GUI and control the entire flow of the evaluator "life cycle"
	 */
	public void evaluate()
	{
		startingIndex=0;
		   this.init();
		   dataEnteredCounter = 0;
		   jcompListToBlink= new  ArrayList <JComponent>();
		   if ( GlobalData.worker != null)
			{
				evaluator =  (Worker) GlobalData.worker;
			}
				else
				{
					try {
						throw new ICMException("could not downcast. the user in global data is not worker!");
					} catch (ICMException e) {
						e.printStackTrace();
					}
				}
		
			
		buildAllRequestsLists() ;
		
	}
	
	
	/**
	 *  set up sizes for panel
	 * @param myEvaluationPanel
	 */
	private void setTuppleSizesForPanel(EvaluationPanel myEvaluationPanel) {
		for (int i=0 ; i< this.NUMOFTABS ; i++ )
		{
			myEvaluationPanel.setNumberOfTupples(i, numberOfTupples[i]);		
		}
		
	}
	/**
	 * build reuqest list
	 */
	public void buildAllRequestsLists() {
	
		requestsToEvaluate.clear();
		requestsToReEvaluate.clear();
		requestsWithTimePending.clear();
		requestsToSetTime.clear();
		System.out.println(evaluator.getId());


		
			SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
				@Override
				 public Void doInBackground() 
				 {
					requestsToEvaluate = new RequestArray(RequestManager.getInstance().getAllRequestsReadyForEvaluation(evaluator));
				    requestsToSetTime =  new RequestArray(RequestManager.getInstance().getAllRequestsForEvaluationWithoutTime(evaluator));
					requestsToReEvaluate = new RequestArray(RequestManager.getInstance().getAllRequestsReadyForReEvaluation(evaluator));
					 requestsWithTimePending = new RequestArray(RequestManager.getInstance().getAllRequestsReadyForEvaluationWithTimePending(evaluator));
					return null;

				}
				@Override
				public void done() 
				{
						System.out.println("Thread worker started building");
						try {
							evaluationPanel = new EvaluationPanel();
							
						} catch (Exception e) {
							e.printStackTrace();
						}
						createDataForPanel();
						setTuppleSizesForPanel(evaluationPanel);
						evaluationPanel.setWhatTobuild();
						evaluationPanel.setStartingIndex(startingIndex);
						evaluationPanel.buildPanel();
						enterDataToPanel(evaluationPanel);
						setListenerToViewDataPanel(evaluationPanel);
						 for (int i =0 ; i< NUMOFTABS ; i++)
				            {
				            	if (evaluationPanel.getTobuild(i) == true)
				            	{
				            		GlobalData.guiMangaer.switchScreen(evaluationPanel);
									System.out.println("Thread worker has finished building");	
									return;
				            }
				            }
						JOptionPane.showMessageDialog(new JFrame(),"There are no requests in need of evaluation", "",JOptionPane.DEFAULT_OPTION);
				            	
				}	
			    };  
			
			worker.execute();
        

         
	}
/**
 *  enter data to panel
 * @param myEvaluationPanel
 */
	void enterDataToPanel(EvaluationPanel myEvaluationPanel)
	{
	   // build the tables with the matrixes
	
	    if (strMtrxRequestsToEvaluate != null && myEvaluationPanel.getTobuild(0))
	    {
		    myEvaluationPanel.getRequestTableListPanel(0).buildTabel(fieldsInTable, strMtrxRequestsToEvaluate);
	
	    }
	    if (strMtrxRequestsToReEvaluate != null && myEvaluationPanel.getTobuild(1))
	    {
		    myEvaluationPanel.getRequestTableListPanel(1).buildTabel(fieldsInTable, strMtrxRequestsToReEvaluate);
	
	    }
	    if (strMtrxRequestsToSetTime != null && myEvaluationPanel.getTobuild(2))
	    {
		    myEvaluationPanel.getRequestTableListPanel(2).buildTabel(fieldsInTable, strMtrxRequestsToSetTime);
	    }
	    if (strMtrxRequestsWithTimePending != null && myEvaluationPanel.getTobuild(3))
	    {
		    myEvaluationPanel.getRequestTableListPanel(3).buildTabel(fieldsInTable, strMtrxRequestsWithTimePending);
	    }
	  
	   
	}
	/**
	 * create data for panel
	 */
	private void createDataForPanel() 
	{
	//Change all RequestArrays into string matrix	
		strMtrxRequestsToEvaluate   = requestsToEvaluate.requestArrayToMatrixEvaluationCommon();
		strMtrxRequestsToReEvaluate = requestsToReEvaluate.requestArrayToMatrixEvaluationCommon();
	    strMtrxRequestsToSetTime    =  requestsToSetTime.requestArrayToMatrixEvaluationCommon();
	    strMtrxRequestsWithTimePending =  requestsWithTimePending.requestArrayToMatrixEvaluationCommon();
	    //this counter counts lines per table for display options
	    this.numberOfTupples[0] = requestsToEvaluate.size();
		this.numberOfTupples[1] = requestsToReEvaluate.size();
		this.numberOfTupples[2] = requestsToSetTime.size();
		this.numberOfTupples[3] = requestsWithTimePending.size() ;
        System.out.println(this.numberOfTupples[0]+" " +this.numberOfTupples[1]+" "+ this.numberOfTupples[2]+" "+this.numberOfTupples[3]);

 }

	

	
	/**
	 * set evlaution time for a request 
	 */
	public void setEvaluationTimeForRequest()
	{	
		setTimeForEvaluation = new SetTimeForEvaluationPanel();
	    GlobalData.guiMangaer.switchScreen(setTimeForEvaluation);
	    setListenerToInputPanel(setTimeForEvaluation);
}
/**
 * sets finish time
 * @param req
 * @throws ICMException
 */
public void finishSetTime(Request req) throws ICMException 
{
    int timeForEval = (Integer)setTimeForEvaluation.getComboBox().getSelectedItem();
	req.setTimeForEvaluation(timeForEval);
	System.out.println("Changing status for request: "+req.getRequestId());
	if (req.getCurrentStatus().getStatus().getsStatus() == RequestStepStatusEnum.EVL_RETURNED_TO_REVALUTION)
	{
		req.changeStatus(new Status(RequestStepStatusEnum.EVL_REAVLAUTION_WITH_TIME_PENDING, RequestMainStatusEnum.OPEN), " Evaluation time waiting inspector approval", timeForEval); 
	}
	else
	{
	req.changeStatus(new Status(RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME_PENDING, RequestMainStatusEnum.OPEN), " Evaluation time waiting inspector approval", timeForEval); 
	}
	JOptionPane.showMessageDialog(new JFrame(),"Your time request was sent to the inspector for approval ", "",JOptionPane.DEFAULT_OPTION);
	if (sendMailOn )
	{
		if (req.getInspector() == null)
		{
			System.out.println("There is no inspector set, check DB validity!!");
		}
		else
		{
		Notificator.sendEmailNotification(req.getInspector().getEmail(), "Dear Inspector. \n "+
		                                      " new request is pending your approval for estimated time of evaluation. Please take the needed steps \n"+
				                              " Thank you, ICM System" );
		}
	}
	GlobalData.request = null;

}
		
	

	/**
	 * checks for data correction
	 * @param myEvaluationReportPanel
	 * @return boolean
	 */
	public boolean checkDataCorrect(EvaluationReportPanel myEvaluationReportPanel)
	{
		boolean result=true;
		if (myEvaluationReportPanel == null)
		{
			return false;
		}
		if (myEvaluationReportPanel.getTxtAreaDescription().getText().length() ==0 ) 
		{
			addToBlink(myEvaluationReportPanel.getLblFieldMissingDescription());
			result = false;
		}
		if (myEvaluationReportPanel.getTxtAreaDesiredChange().getText().length() == 0) 
		{
			addToBlink(myEvaluationReportPanel.getLblFieldMissingResult());
			result = false;
		}
		if (myEvaluationReportPanel.getTxtAreaLocation().getText().length() == 0) 
		{
			addToBlink(myEvaluationReportPanel.getLblFieldMissingLocation());

			result = false;
		}
		if (myEvaluationReportPanel.getTxtAreaRisks().getText().length() == 0) 
		{
			addToBlink(myEvaluationReportPanel.getLblFieldMissingRisks());
			
		}
		if (result == false)
		{
			addToBlink(myEvaluationReportPanel.getLblFieldsMissingWarningText());
			blink();
		}
		return result;
		
	}
	/**
	 * blink graphic option
	 */
	public void blink()
	{
		(new Thread() {
			public void run()
			{
							
						for (int j=0 ; j<5 ; j++ )
						{
							for (JComponent jcomp : jcompListToBlink)
							{
								jcomp.setVisible(true);
							}
						try {
							sleep(200);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						for (JComponent jcomp : jcompListToBlink)
						{
							jcomp.setVisible(false);
						}
	
					
				}
				jcompListToBlink.clear();
			}
		}).start();
	}
	/**
	 *  add label to blink animation
	 * @param lbl
	 */
	public void addToBlink(JComponent lbl) 
	{
	   jcompListToBlink.add(lbl);

	}
				
	
	
	/**
	 * adds evaluation report
	 */
	public void addEvaluationReport() 
	{
		evaluationReportPanel = new EvaluationReportPanel();
		GlobalData.guiMangaer.switchScreen(evaluationReportPanel);
		evaluationReportPanel.btnAskForMoreTime.addActionListener( new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{	
				askForMoreTime(currentRequest);
			}
		});
		setListenerToInputPanel(evaluationReportPanel);
	}
	/**
	 *  finish evlaution method
	 * @param req
	 * @throws ICMException
	 */
	public void finishEvaluation(Request req) throws ICMException 
	{
	String strLocation = evaluationReportPanel.getTxtAreaLocation().getText();
	String strDescription = evaluationReportPanel.getTxtAreaDescription().getText();
	String strDesiredChange = evaluationReportPanel.getTxtAreaDesiredChange().getText();
	String strRisk = evaluationReportPanel.getTxtAreaRisks().getText();
	int daysEstimate =0;

	if ( evaluationReportPanel.getCmbBoxSetTime().getSelectedItem() instanceof Integer)
	{
		 daysEstimate = (Integer)evaluationReportPanel.getCmbBoxSetTime().getSelectedItem();
	}
	else
	{
		System.out.println("Warning! time was not properly selected or copied Evaluator controller action listener");
	}
	Report evlRepNewReport = null;
	try 
	{
		Report r = new Report();
		File file = r.buildEvaluationReport(currentRequest, strLocation, strDescription, strDesiredChange, strRisk, daysEstimate);
		PDFfile pdf = new PDFfile();
		pdf.read(file.getPath());
		evlRepNewReport = new Report(evaluator, " ", pdf, new Date(),ReportType.EVALUATION);
	} 
	catch (IOException e) 
	{
        System.out.println("Error creating pdf file in evaluation report called from action listener evaluation report");
		e.printStackTrace();
	}
	if (req!= null && evlRepNewReport!=null )
	{
		req.addReport(evlRepNewReport); 
		req.changeStatus(new Status(RequestStepStatusEnum.EVL_PASSED, RequestMainStatusEnum.OPEN), " Evaluation passed",new Integer(req.getTimeForReview())); 
		JOptionPane.showMessageDialog(new JFrame(),"Evaluation report addedfor request number "+req.getRequestId(), "",JOptionPane.DEFAULT_OPTION);
		GlobalData.request = null;

     
	}
}
	/**
	 * revluate
	 */
public void reEvaluate()
{
	myReevaluationPanel = new ReevaluationPanel();
	GlobalData.guiMangaer.switchScreen(myReevaluationPanel);
	setListenerToInputPanel(myReevaluationPanel);
	}

public void finishReEvaluate(Request req)
{
	String addedNotes = myReevaluationPanel.getTxtFieldNotes().getText();
	if (addedNotes.length()>0)
	{ 
		Report evlRepNewReport = null;
		Report r = new Report();
		File file = r.buildreEvaluationReport(currentRequest, addedNotes);
		PDFfile pdf = new PDFfile();
		pdf.read(file.getPath());
		evlRepNewReport = new Report(evaluator, " ", pdf, new Date(),ReportType.EVALUATION);
		if (req!= null && evlRepNewReport!=null )
		{
			try {
				req.addReport(evlRepNewReport);
			} catch (ICMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		
		req.changeStatus(new Status(RequestStepStatusEnum.EVL_PASSED, RequestMainStatusEnum.OPEN), " Evaluation passed",new Integer(req.getTimeForReview())); 
		JOptionPane.showMessageDialog(new JFrame(),"Evaluation report add for request number "+req.getRequestId(), "",JOptionPane.DEFAULT_OPTION);
		GlobalData.request = null;
		}
	}
	else
		JOptionPane.showMessageDialog(new JFrame(),
				"Please enter some more information",
				"Error",
				JOptionPane.ERROR_MESSAGE);
		
		
}

	@Override
	/*
	 * (non-Javadoc)
	 * @see Controllers.GenericToolsForController.BaseClass#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e)
	{
		if (evaluationPanel != null)
		{
				if (e.getSource() == evaluationPanel.btnBack) 
				{
					GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);
					return;
				}
	           if (e.getSource() == evaluationPanel.btnRefresh )
				{
	        	   startingIndex = evaluationPanel.getMainTabbedPane().getSelectedIndex();
	        	        this.init();
						this.evaluate();
						return;
					}
	           if (e.getSource() == evaluationPanel.btnNext )
				{
	        	   if (evaluationPanel.getMainTabbedPane().getSelectedComponent() instanceof GenericTabel )
	        	   {
	        	   GenericTabel currentPanel = (GenericTabel) evaluationPanel.getMainTabbedPane().getSelectedComponent();
	        	   if (currentPanel.isChosen())
	        	   {
	        		   int intIndexOfChosen = currentPanel.getChosen();
	        		   int intChosenTab = -1;
	        		   for (int i=0; i< NUMOFTABS ; i++)
	        			   {
	        			   if (evaluationPanel.getRequestTableListPanel(i) == currentPanel)
	        			   {
	        				   intChosenTab = i;
	        			   }
	        			   }
	        		   if (intChosenTab<0) {
	        			   System.out.println("Could not find the right panel action performed next button evaluator controller");
	        			   return;
	        		   }
	        		   switch (intChosenTab)
	        		   {
	        		   case 0:
	        			   currentRequest = requestsToEvaluate.get(intIndexOfChosen);
	        			   break;
	        		   case 1:
	        			   currentRequest = requestsToReEvaluate.get(intIndexOfChosen);
	        			   break;
	        		   case 2:
	        			   currentRequest = requestsToSetTime.get(intIndexOfChosen);
	        			   break;
	        		   case 3:
	        			   currentRequest = requestsWithTimePending.get(intIndexOfChosen);
	        			   break;
	        			   		
	        			 default:
	        				 System.out.println("Should not have gotten to here - defualt in switch case in action performed next buttons");
	        		   }
	        		   System.out.println("You chose request number: "+currentRequest.getRequestId());
        			   GlobalData.request = currentRequest;
	        		   if (currentRequest!=null && (currentRequest.isEvalReadyForEvaluation() ))
	        		   {
	        			   addEvaluationReport();
	        		   }
	        		   else
	        		   {
	        			   if (currentRequest!=null && currentRequest.isEvalTimeToSet())
	        			   {
	        				   setEvaluationTimeForRequest();
	        			   }
	        			   else 
	        			   {
	        				   if (currentRequest!=null && currentRequest.isEvalReadyForReEvaluation())
	        				   {
	        					  reEvaluate();
	        				   }
	        				   
	        			   }
	        		   }
	        	   }
	        	   else
					{
						JOptionPane.showMessageDialog(new JFrame(),
								"To Continue you must Choose Reuquest",
								"Error",
								JOptionPane.ERROR_MESSAGE);
					}
	        	   }
					}
			}
		if (evaluationReportPanel != null)
		{
				if (e.getSource() == evaluationReportPanel.btnBack) 
				{
				     this.init();
					this.evaluate();
					return;
				}
				else
					if (e.getSource() == evaluationReportPanel.btnSubnit)
					{
						if (checkDataCorrect(evaluationReportPanel))
						{
						   try {
							finishEvaluation(currentRequest);
							GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);
						} catch (ICMException e1) {
							e1.printStackTrace();
						}
						}
					}
		}
		if (setTimeForEvaluation != null) 
		{
			if (e.getSource() == setTimeForEvaluation.btnBack) 
			{
				GlobalData.guiMangaer.switchScreen(evaluationPanel);

				return;
			}
			else
				if (e.getSource() == setTimeForEvaluation.btnSubnit)
				{
					    try {
							finishSetTime(currentRequest);
						} catch (ICMException e1) {
							e1.printStackTrace();
						}
						GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);

				}
		}
		if (myReevaluationPanel != null)
		{
			if (e.getSource() == myReevaluationPanel.btnBack) 
			{
				GlobalData.guiMangaer.switchScreen(evaluationPanel);

				return;
			}
			else
			{
				if (e.getSource() == myReevaluationPanel.btnSubnit)
				{
							finishReEvaluate(currentRequest);
						GlobalData.guiMangaer.switchScreen(GlobalData.mainScreen);

				}
		
				}
		}
	
	}
}
